﻿using System;
using Gp.Scripts.Equip;
using QFramework;
using Sirenix.OdinInspector;
using UnityEngine;

namespace Gp.Scripts.Core {
    [RequireComponent(typeof(HumanoidModel))]
    public class CombatantWeaponPivot : MonoBehaviour {
        [Title("手持武器锚点")]
        [LabelText("近战武器锚点")]
        public Transform meleeWeaponPivot;
        [LabelText("盾牌锚点")]
        public Transform shieldPivot;
        [LabelText("远程武器锚点")]
        public Transform rifePivot;


        [Title("悬挂武器锚点")]
        [LabelText("腰部锚点")]
        public Transform hipsPivot;

        [LabelText("背部锚点")]
        public Transform backPivot;

        [LabelText("背部锚点（步枪）")]
        public Transform backGunPivot;


        public HumanoidModel Model { get; set; }

        private void Start() {
            Model = GetComponent<HumanoidModel>();
            if (TryGetComponent<UnitAnimatorEventTrigger>(out var eventTrigger)) {
                eventTrigger.OnEventTrigger += args => {
                    if (args != UnitAnimEventType.WeaponTakeOut.EventName()) return;
                    OnWeaponTakeOutTrigger();
                };
            }
        }

        public UnitWeaponModel CurWeapon { get; private set; }
        public UnitWeaponModel Shield { get; private set; }

        public int SwitchWeaponModel(UnitWeaponModel model, WeaponEntity weapon) {
            if (model == null) {
                CleanUp();
                return 0;
            }
            
            
            var obj = Instantiate(model);
            CleanUp();
            obj.gameObject.SetAllLayer(Model.gameObject.layer);
            obj.Init(this, weapon);
            CurWeapon = obj;
            return obj.code.CodeNumber();
        }




        public void BuildShield(UnitWeaponModel shieldModel, WeaponEntity weapon) {
            if (shieldModel == null) return;
            if (Shield) Destroy(Shield.gameObject);
            var obj = Instantiate(shieldModel, shieldPivot, false);
            obj.gameObject.layer = Model.gameObject.layer;
            obj.Init(this, weapon);
            Shield = obj;
        }






        public void BeforeWeaponTakeOut() {
            if (CurWeapon == null || CurWeapon.code == WeaponTypeCode.Shield) return;

            Transform parent = TakeOutFrom(CurWeapon.code);
            if (parent == null) {
                CleanUp();
                return;
            }

            CurWeapon.transform.SetParent(parent, false);
        }
        
        
        
        
        
        
        public void OnWeaponTakeOutTrigger() {
            if (CurWeapon == null || CurWeapon.code == WeaponTypeCode.Shield) return;

            Transform parent = null;
            if (CurWeapon.code.IsMeleeWeapon()) {
                parent = meleeWeaponPivot;
            } else if (CurWeapon.code.IsShield()) {
                parent = shieldPivot;
            }
            else {
                parent = rifePivot;
            }

            if (parent == null) return;
            
            CurWeapon.transform.SetParent(parent, false);
        }



        private Transform TakeOutFrom(WeaponTypeCode code) {
            return code switch {
                WeaponTypeCode.Rife => backGunPivot,
                WeaponTypeCode.FireSpit => backGunPivot,
                // WeaponTypeCode.Stick => backPivot,
                WeaponTypeCode.GreatSword => backPivot,
                WeaponTypeCode.Shield => backPivot,
                _ => hipsPivot,
            };
        }
        
        


        private void CleanUp() {
            if (CurWeapon)
                Destroy(CurWeapon.gameObject);
        }


#if UNITY_EDITOR
        [Title("工具")]
        [SerializeField]
        private CombatantWeaponPivot template;

        private const HumanBodyBones ShieldBone = HumanBodyBones.LeftLowerArm;
        private const HumanBodyBones MeleeBone = HumanBodyBones.RightHand;
        private const HumanBodyBones RifeBone = HumanBodyBones.RightHand;

        private const HumanBodyBones HipsBone = HumanBodyBones.Hips;
        private const HumanBodyBones BackBone = HumanBodyBones.UpperChest; 
        
        
        [Button("模板赋值")]
        private void Copy() {
            if (template == null) return;
            var animator = GetComponent<Animator>();
            if (animator == null) return;
            
            

            if (meleeWeaponPivot) DestroyImmediate(meleeWeaponPivot.gameObject); 
            if (shieldPivot) DestroyImmediate(shieldPivot.gameObject); 
            if (rifePivot) DestroyImmediate(rifePivot.gameObject); 
            if (hipsPivot) DestroyImmediate(hipsPivot.gameObject);
            if (backPivot) DestroyImmediate(backPivot.gameObject);
            if (backGunPivot) DestroyImmediate(backGunPivot.gameObject);
            
            
            
            meleeWeaponPivot = BuildTransWithParent(template.meleeWeaponPivot, MeleeBone);
            shieldPivot = BuildTransWithParent(template.shieldPivot, ShieldBone);
            rifePivot = BuildTransWithParent(template.rifePivot, RifeBone);
            hipsPivot = BuildTransWithParent(template.hipsPivot, HipsBone);
            backPivot = BuildTransWithParent(template.backPivot, BackBone);
            backGunPivot = BuildTransWithParent(template.backGunPivot, BackBone);

            
            
            
            

            UnityEditor.EditorUtility.SetDirty(this);
            
            
            Transform BuildTransWithParent(Transform templateTrans, HumanBodyBones bone) {
                Transform parent = animator.GetBoneTransform(bone);
                if (!templateTrans || !parent) return null;
            
                var obj = new GameObject(templateTrans.name);
                var objTrans = obj.transform; 
            
                objTrans.SetParent(parent);
                objTrans.localPosition = templateTrans.localPosition;
                objTrans.localRotation = templateTrans.localRotation;
                objTrans.localScale = templateTrans.localScale;
            
                return objTrans;
            }
        } 
#endif


        private void OnAttackHitTrigger(BaseUnit attackTarget) {
            // if (attackTarget != null && CurWeapon != null) CurWeapon.OnAttackHitTrigger(attackTarget);
        }

        public void OnUnitModelAnimationEvent(string eventName) {
            if (CurWeapon) CurWeapon.OnUnitModelAnimationEvent(eventName);
        }
    }
}